package com.enation.app.javashop.core.promotion.shetuan.service.impl;

import com.enation.app.javashop.core.base.CachePrefix;
import com.enation.app.javashop.core.base.message.ShetuanChangeMsg;
import com.enation.app.javashop.core.base.rabbitmq.AmqpExchange;
import com.enation.app.javashop.core.goods.GoodsErrorCode;
import com.enation.app.javashop.core.goods.model.dos.GoodsDO;
import com.enation.app.javashop.core.goods.model.dto.BuyRecord;
import com.enation.app.javashop.core.goods.model.dto.GoodsQuantityRefreshDTO;
import com.enation.app.javashop.core.goods.model.enums.Permission;
import com.enation.app.javashop.core.goods.service.GoodsManager;
import com.enation.app.javashop.core.goods.service.GoodsQuantityManager;
import com.enation.app.javashop.core.member.model.dos.Member;
import com.enation.app.javashop.core.member.service.MemberManager;
import com.enation.app.javashop.core.promotion.shetuan.model.dos.ShetuanDO;
import com.enation.app.javashop.core.promotion.shetuan.model.dos.ShetuanGoodsDO;
import com.enation.app.javashop.core.promotion.shetuan.model.enums.ShetuanGoodsStatusEnum;
import com.enation.app.javashop.core.promotion.shetuan.model.enums.ShetuanStatusEnum;
import com.enation.app.javashop.core.promotion.shetuan.service.ShetuanGoodsManager;
import com.enation.app.javashop.core.promotion.shetuan.service.ShetuanGoodsOperateManager;
import com.enation.app.javashop.core.promotion.shetuan.service.ShetuanOperateManager;
import com.enation.app.javashop.core.trade.order.model.vo.OrderSkuVO;
import com.enation.app.javashop.framework.database.DaoSupport;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.util.DateUtil;
import com.enation.app.javashop.framework.util.StringUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 社区团购服务
 *
 * @author admin
 * @version vv1.0.0
 * @since vv7.1.0
 * 2019-01-21 15:17:57
 */
@Service
public class ShetuanOperateManagerImpl implements ShetuanOperateManager {
    protected final Log logger = LogFactory.getLog(this.getClass());

    @Autowired
    @Qualifier("tradeDaoSupport")
    private DaoSupport tradeDaoSupport;
    @Autowired
    private GoodsManager goodsManager;
    @Autowired
    private ShetuanGoodsManager shetuanGoodsManager;
    @Autowired
    private ShetuanGoodsOperateManager shetuanGoodsOperateManager;
    @Autowired
    private AmqpTemplate amqpTemplate;

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private MemberManager memberManager;
    @Autowired
    private GoodsQuantityManager goodsQuantityManager;


    /**
     * 下线社区团购活动
     * 1.删除es失效社区团购活动商品
     *
     * @param shetuanId
     */
    @Override
    public ShetuanDO offLine(Integer shetuanId) {
        ShetuanDO shetuanDO = this.tradeDaoSupport.queryForObject(ShetuanDO.class, shetuanId);
        if (shetuanDO == null) {
            return null;
        }
        //更新mysql
        shetuanDO.setStatus(ShetuanStatusEnum.OFF_LINE.getIndex());
        this.tradeDaoSupport.update(shetuanDO, shetuanId);
        // 更新es
        this.updateShetuanGoodsIndex(shetuanId);
        return shetuanDO;
    }

    /**
     * 上线社区团购活动
     *
     * @param shetuanId
     */
    @Override
    public ShetuanDO onLine(Integer shetuanId) {
        ShetuanDO shetuanDO = this.tradeDaoSupport.queryForObject(ShetuanDO.class, shetuanId);
        // 检查是否可以手动上线
        checkOnLine(shetuanDO);
        /**设置成已上线*/
        shetuanDO.setStatus(ShetuanStatusEnum.ON_LINE.getIndex());
        this.tradeDaoSupport.update(shetuanDO, shetuanId);

        // 同步库存(参团数量和商品库存) 社团商品的参团数量 = 商品的可用库存
        shetuanGoodsOperateManager.syncGoodsQuantityToGoodsNum(shetuanId);

        // 上线社区团购商品（只能更新已上架的商品）
        List<ShetuanGoodsDO> shetuanGoodsDOS =   this.updateShetuanGoodsIndex(shetuanId);

        // 同步库存(参团数量和商品库存) 总库存 = 商品参团数量（可用库存）+ 待发货数量
        // shetuanGoodsOperateManager.syncGoodsNumToGoodsQuantity(shetuanGoodsDOS);

        // 上线活动涉及的所有商品上架
        List<Integer> goodsIds = shetuanGoodsDOS.stream().map(ShetuanGoodsDO::getGoodsId).collect(Collectors.toList());
        this.goodsManager.ups(shetuanDO.getSellerId(),goodsIds.toArray(new Integer[goodsIds.size()]));

        // 非当日活动商品全部下架
        underGoods(shetuanDO,goodsIds);

        return shetuanDO;
    }

    private void underGoods(ShetuanDO shetuanDO,  List<Integer> shetuanGoodsIds) {
        Integer sellerId = shetuanDO.getSellerId();

        List<Object> term = new ArrayList<>();

        StringBuilder sql = new StringBuilder().append(" SELECT * FROM es_goods WHERE seller_id=? and market_enable=1  ");
        term.add(sellerId);

        processPintuanGoodsIds(sellerId,term, sql);

        processShetuanGoodsIds(shetuanGoodsIds, term, sql);

        processSeckillGoodsIds(sellerId,  term, sql);

        List<GoodsDO> underGoodsList = this.tradeDaoSupport.queryForList(sql.toString(), GoodsDO.class,term.toArray());

        if (CollectionUtils.isEmpty(underGoodsList)) {
            return;
        }
        List<Integer> underGoodsIds = underGoodsList.stream().map(GoodsDO::getGoodsId).collect(Collectors.toList());
        this.goodsManager.under(underGoodsIds.toArray(new Integer[underGoodsIds.size()]),"每日定时下线非运营商品", Permission.SELLER);
    }

    private void processSeckillGoodsIds(Integer sellerId,  List<Object> term, StringBuilder sql) {
        long startOfTodDay = DateUtil.startOfTodDay();
        List<Map> seckillGoodsIds = tradeDaoSupport.queryForList(
                "SELECT goods_id FROM es_seckill_apply WHERE start_day=? and seller_id=? ",
                startOfTodDay,sellerId);

        if (!CollectionUtils.isEmpty(seckillGoodsIds)) {
            String[] temp = new String[seckillGoodsIds.size()];
            for (int i = 0; i < seckillGoodsIds.size(); i++) {
                temp[i] = "?";
                term.add(seckillGoodsIds.get(i).get("goods_id"));
            }
            String seckillGoodsIdsStr = StringUtil.arrayToString(temp, ",");
            sql.append(" and  goods_id not in (" + seckillGoodsIdsStr + ")");
        }
    }

    private void processShetuanGoodsIds(List<Integer> shetuanGoodsIds, List<Object> term, StringBuilder sql) {
        if (!CollectionUtils.isEmpty(shetuanGoodsIds)) {
            String[] temp = new String[shetuanGoodsIds.size()];
            for (int i = 0; i < shetuanGoodsIds.size(); i++) {
                temp[i] = "?";
                term.add(shetuanGoodsIds.get(i));
            }
            String shetuanGoodsIdsStr = StringUtil.arrayToString(temp, ",");
            sql.append(" and  goods_id not in (" + shetuanGoodsIdsStr + ")");
        }
    }

    private void processPintuanGoodsIds(Integer sellerId,  List<Object> term, StringBuilder sql) {
        long now = DateUtil.getDateline();

        List<Map> pintuanGoodsIds = tradeDaoSupport.queryForList(
                "SELECT goods_id FROM es_pintuan_goods pg LEFT JOIN es_pintuan pt ON pt.promotion_id=pg.pintuan_id WHERE pt.start_time <= ? and  pt.end_time  >= ? and pt.seller_id=? ",
                now,now,sellerId);

        if (!CollectionUtils.isEmpty(pintuanGoodsIds)) {
            String[] temp = new String[pintuanGoodsIds.size()];
            for (int i = 0; i < pintuanGoodsIds.size(); i++) {
                temp[i] = "?";
                term.add(pintuanGoodsIds.get(i).get("goods_id"));
            }
            String pintuanGoodsIdsStr = StringUtil.arrayToString(temp, ",");
            sql.append(" and  goods_id not in (" + pintuanGoodsIdsStr + ")");
        }
    }


    private void checkOnLine(ShetuanDO shetuanDO) {

        if (DateUtil.getDateline() >= shetuanDO.getEndTime()) {
            throw new ServiceException("500","此活动已过期，不能手动上线");
        }
        if (DateUtil.getDateline() <= shetuanDO.getStartTime()) {
            throw new ServiceException("500","此活动未开始，不能手动上线");
        }
    }


    @Override
    public List<ShetuanGoodsDO> updateShetuanGoodsIndex(Integer shetuanId) {
        /**查询出商此活动对应的商品信息，将对应的上线商品信息重新更新索引*/
        List<ShetuanGoodsDO> list = this.shetuanGoodsManager.getByShetuanAndStatus(shetuanId, new Integer[]{ShetuanGoodsStatusEnum.ON_LINE.getIndex(),ShetuanStatusEnum.NEW.getIndex()});
        List<Integer> skuList = new ArrayList<>();
        for (ShetuanGoodsDO shetuanGoodsDO : list) {
            skuList.add(shetuanGoodsDO.getSkuId());
        }
        if (skuList.size() > 0) {
            this.amqpTemplate.convertAndSend(AmqpExchange.SHETUAN_CHANGE, AmqpExchange.SHETUAN_CHANGE + "_ROUTING", new ShetuanChangeMsg(shetuanId, skuList));
        }
        return list;
    }

    @Override
    @Transactional(value = "tradeTransactionManager", propagation = Propagation.REQUIRED, rollbackFor = {Exception.class})
    public void updateBuyRecord(List<OrderSkuVO> list,Integer memberId) {
        Member member = memberManager.getMemberById(memberId);
        for (OrderSkuVO orderSkuVO : list) {
            // 1. 用户购买记录
            String buyRecordKey = CachePrefix.BUY_REC.getPrefix() + orderSkuVO.getSkuId();
            BuyRecord buyRecord = new BuyRecord();
            buyRecord.setMemberName(member.getNickname());
            buyRecord.setMemberFace(member.getFace());
            buyRecord.setBuyTime(DateUtil.getDateline());
            buyRecord.setBuyNum(orderSkuVO.getNum());
            redisTemplate.opsForList().rightPush(buyRecordKey, buyRecord);

        }
    }


}
